Semantik Web • Hafta 10
SWRL API & SQWRL
Kuralları Java'dan çalıştırmak, SQWRL ile sorgulamak ve alerji sisteminin uçtan uca tamamlanması
Lisansüstü Semantik Web Dersi • CMPE 583
Hafta 10 • Kazanımlar
Bu hafta sonunda
- SWRL API ile kural motorunu Java'dan çalıştırabileceksiniz.
- Kuralları kodla oluşturup ontolojiye ekleyebileceksiniz.
- SQWRL sorgularıyla çıkarım sonuçlarını raporlayabileceksiniz.
- Protégé SWRLTab / SQWRLTab akışını doğru sırayla uygulayabileceksiniz.
- Reasoner ile kural motorunun iş bölümünü açıklayabileceksiniz.
01
SWRL Nedir?
Tanım, konum ve API'ye neden ihtiyaç var.
SWRL: Semantic Web Rule Language
OWL DL'in tanımlama mantığı ile RuleML'in Horn kurallarını birleştiren, W3C'ye sunulmuş bir kural dilidir.
Ne yapar
Var olan bilgiden yeni bilgi türetir.
Nerede durur
OWL'un üstünde, sorgu katmanının altında.
Projede
S1–S7: risk zinciri ve BMI hesabı.
Neden SWRL API gerekli?
| İhtiyaç | Protégé SWRLTab | SWRL API |
| Kuralı bir kez çalıştırmak | Yeter | Yeter |
| Her istekte çalıştırmak | İnsan gerekir | Otomatik |
| Web servisine bağlamak | Mümkün değil | Doğal |
| Kuralı kodla üretmek | Elle yazılır | Programatik |
| Sonucu JSON'a çevirmek | Yok | Kolay |
| Birim testi | Yok | JUnit |
Protégé kuralı tasarlamak, SWRL API kuralı işletmek içindir.
Üç bileşeni ayırt edin
SWRLAPI
Kuralı okur, yazar, motora taşır. Ontoloji tarafı.
Drools
Gerçek kural motoru. İleri zincirleme yapar.
SQWRL
Kural sonuçlarını sorgular. Ontolojiyi değiştirmez.
Üçü tek Maven bağımlılığıyla gelir: swrlapi-drools-engine.
Reasoner ile kural motoru farkı
| Boyut | HermiT / Pellet | Drools (SWRL) |
| Ne yapar | Sınıflandırır, denetler | Kural gövdesi eşleşirse baş yazar |
| Aritmetik | Yok | Var |
| Sonuç kalıcı mı | Bellekte (geçici) | Ontolojiye yazılabilir |
| Tutarsızlık bulur mu | Evet | Hayır |
| Projede | ADIM 3 ve 7 denetim | ADIM 5 çıkarım |
İkisi birbirinin yerine geçmez: HermiT sınıflandırır, Drools hesaplar ve zincirler.
02
SWRL API Kullanımı
Küçük küçük örneklerle, satır satır.
Adım 0 — Tek bağımlılık
<dependency>
<groupId>edu.stanford.swrl</groupId>
<artifactId>
swrlapi-drools-engine
</artifactId>
<version>2.1.2</version>
</dependency>
- Drools'u kendisi getirir — ayrıca eklemeyin.
- OWL API 4.x dalını bekler.
- Java 8 ile en güvenli çalışır.
Adım 1 — Motoru kur ve çalıştır
SWRLRuleEngine engine =
SWRLAPIFactory.createSWRLRuleEngine(ont);
engine.infer();
- createSWRLRuleEngine ontolojiyi alır, kuralları bulur, Drools'a taşır.
- infer() üç işi birlikte yapar: aktar, çalıştır, sonucu ontolojiye yaz.
- Protégé'deki üç düğmenin (OWL+SWRL → Drools, Run, Drools → OWL) tek satırlık karşılığıdır.
Adım 2 — Kuralları listele
SWRLRuleEngine engine = SWRLAPIFactory.createSWRLRuleEngine(ont);
for (SWRLAPIRule r : engine.getSWRLRules())
System.out.println(r.getRuleName() + " : " + r.getComment());
S1_FishRisk : Sodium Ascorbate balik riski
S4_BMI : Kilo ve boydan BMI
S6_GenericAllergen : Genel risk zinciri
S7_RiskClass : Riskli kisi sinifi
Kural adı burada işe yarar: hangi kuralın yüklendiğini çalıştırmadan önce görürsünüz.
Adım 3 — Önce ve sonra ölç
int before = ont.getAxiomCount();
engine.infer();
int after = ont.getAxiomCount();
System.out.println("Kural cikti: " + (after - before) + " aksiyom");
Kural cikti: 14 aksiyom
Bu iki satır, en değerli hata ayıklama aracınızdır: 0 görüyorsanız literal tipi ya da namespace hatası vardır.
Adım 4 — Çıkarılan bilgiyi oku
engine.infer();
EntitySearcher.getObjectPropertyValues(
ind("TC_001"), op("Effected_Allergen"), ont)
.forEach(v -> System.out.println("Suclu katki: " + v));
Suclu katki: Nisin
infer() sonucu asserted yazdığı için normal EntitySearcher ile okunur; reasoner gerekmez.
Adım 5 — Hesaplanan değeri oku
EntitySearcher.getDataPropertyValues(ind("TC_004"), dp("hasBMI"), ont)
.forEach(l -> System.out.printf("BMI = %.2f%n", l.parseDouble()));
BMI = 33.43
parseDouble() literalin tipini denetler; string gelirse istisna atar — sessiz hatayı görünür yapar.
Adım 6 — Kuralın yazdığı sınıf üyeliği
EntitySearcher.getIndividuals(cls("PersonAtRisk"), ont)
.forEach(i -> System.out.println(i.getIRI().getShortForm()));
TC_001
TC_002
TC_003
TC_004
Kural öncesi bu liste boştu. Dört kişinin de riskli çıkması, S6 + S7 zincirinin çalıştığının kanıtıdır.
Adım 7 — Kuralı metin olarak ekle
SWRLRuleEngine engine = SWRLAPIFactory.createSWRLRuleEngine(ont);
engine.createSWRLRule("S8_Obese",
"Person(?p) ^ hasBMI(?p, ?b) "
+ "^ swrlb:greaterThanOrEqual(?b, 30.0) -> ObesePerson(?p)");
engine.infer();
En pratik yol: kuralı Protégé sözdizimiyle yazarsınız, API ayrıştırır. Hafta 07'de gördüğümüz SWRLRule nesnesi kurmaya gerek kalmaz.
Adım 8 — Hatayı yakala
try {
engine.createSWRLRule("S9",
"Person(?p) ^ hasAge(?p, ?a) "
+ "^ swrlb:greaterThan(?a, \"18\") -> Adult(?p)"); // esik metin!
engine.infer();
} catch (SWRLParseException | SWRLRuleEngineException e) {
System.err.println("Kural hatasi: " + e.getMessage());
}
Kural hatasi: incompatible argument types for swrlb:greaterThan (xsd:int, xsd:string)
Doğrusu — eşik tipli sayı olarak yazılır
"Person(?p) ^ hasAge(?p, ?a) ^ swrlb:greaterThan(?a, 18) -> Adult(?p)"
Adım 9 — Çıkarımı kalıcı yap
engine.infer();
man.saveOntology(ont, new RDFXMLDocumentFormat(),
IRI.create(new File("ALLERGY_INFERRED.owl").toURI()));
Artık dosyada Effected_Allergen, hasBMI ve PersonAtRisk bildirimleri yazılı durur. Bu dosya Protégé'de açıldığında kural motoru olmadan da riskleri gösterir.
03
SQWRL ile Sorgulama
Kural gövdesi + select: rapor üretmenin en kısa yolu.
SQWRL: Semantic Query-Enhanced Web Rule Language
- SWRL kuralının başını bir sorgu operatörüyle değiştirir.
- Ontolojiyi değiştirmez — sadece tablo döndürür.
- Gövde sözdizimi SWRL ile birebir aynıdır.
# SWRL — yazar
Person(?p) ^ hasAge(?p,?a)
^ swrlb:greaterThan(?a,18)
-> Adult(?p)
# SQWRL — sorar
Person(?p) ^ hasAge(?p,?a)
^ swrlb:greaterThan(?a,18)
-> sqwrl:select(?p, ?a)
Q1 — Kişi başına BMI
Person(?p) ^ hasName(?p, ?n) ^ hasBMI(?p, ?b)
-> sqwrl:select(?n, ?b)
Ayse 23.92
FATMA 28.26
MEHMET 26.60
AYNUR 33.43
Bu sorgu ancak infer() sonrası sonuç verir — hasBMI S4 kuralının ürünüdür.
Q2 — Riskli seçimler ve suçlu katkı
Person(?p) ^ hasName(?p, ?n) ^ ChooseProduct(?p, ?u)
^ Effected_Allergen(?p, ?f)
-> sqwrl:select(?n, ?u, ?f)
Ayse EAN_00004 Nisin
FATMA EAN_00003 Casein
MEHMET EAN_00003 Casein
MEHMET EAN_00003 Sodium_Ascorbite
AYNUR EAN_00002 Soy_Lecitin
MEHMET iki satırda görünür: iki alerjisi iki farklı katkıdan tetikleniyor.
Q3 — Sırala, say, sınırla
Person(?p) ^ hasName(?p, ?n) ^ hasBMI(?p, ?b)
-> sqwrl:select(?n, ?b) ^ sqwrl:orderByDescending(?b)
^ sqwrl:limit(2)
AYNUR 33.43
FATMA 28.26
# katki sayisi
Product(?u) ^ Contain(?u, ?f)
-> sqwrl:count(?f)
SQWRL operatörleri
| Operatör | İşi |
| sqwrl:select | Sütun seçer |
| sqwrl:selectDistinct | Tekrarları atar |
| sqwrl:count / sum / avg / min / max | Toplulaştırma |
| sqwrl:orderBy / orderByDescending | Sıralama |
| sqwrl:limit | Satır sınırı |
| sqwrl:columnNames | Sütun başlığı |
| sqwrl:makeSet / difference / intersection | Küme işlemleri |
Küme farkı: "riskli olmayan kişiler"
Person(?p) ^ sqwrl:makeSet(?all, ?p)
^ PersonAtRisk(?r) ^ sqwrl:makeSet(?risky, ?r)
^ sqwrl:difference(?safe, ?all, ?risky)
-> sqwrl:select(?safe)
Hafta 07'de SWRL ile yazamadığımız olumsuzlama, SQWRL'de küme farkıyla çözülür. Sorgu düzeyinde kapalı dünya varsayımı yapılabilir; kural düzeyinde yapılamaz.
Java — SQWRL sorgusu çalıştır
SQWRLQueryEngine q = SWRLAPIFactory.createSQWRLQueryEngine(ont);
SQWRLResult res = q.runSQWRLQuery("Q1",
"Person(?p) ^ hasName(?p, ?n) ^ hasBMI(?p, ?b) "
+ "-> sqwrl:select(?n, ?b)");
while (res.next())
System.out.printf("%-8s %.2f%n",
res.getValue("n").getLiteral(),
res.getValue("b").asLiteralResult().getDouble());
Sorgu adı ("Q1") zorunludur; sonuçlar bu adla önbelleğe alınır.
SQWRLResult: satır ve sütun
| Metot | Döndürdüğü |
| next() | Sonraki satıra geçer (JDBC gibi) |
| getNumberOfRows() | Satır sayısı |
| getValue("n") | Değişken adıyla hücre |
| asLiteralResult() | Literal olarak yorum |
| getNamedIndividual("p") | Birey olarak yorum |
Yanlış tip metodunu çağırmak istisna atar — bu iyidir, sessiz hata olmaz.
Java — sorgudan rapor üret
List<Map<String,String>> rows = new ArrayList<>();
SQWRLResult r = q.runSQWRLQuery("Q2", RISK_QUERY);
while (r.next()) {
Map<String,String> row = new LinkedHashMap<>();
row.put("kisi", r.getValue("n").getLiteral());
row.put("urun", r.getValue("u").toString());
row.put("katki", r.getValue("f").toString());
rows.add(row);
}
Bu liste doğrudan JSON'a çevrilerek Hafta 06'daki REST uç noktasından döndürülür — sistem böylece tamamlanır.
04
Protégé Arayüzünde
SWRLTab ve SQWRLTab ekran ekran.
Protégé ekranı: SWRLTab
EntitiesSWRLTabSQWRLTab
NameRule
S6_GenericAllergenPerson(?p) ^ hasAllergy(?p,?al) ^ … → Effected_Allergen(?p,?f)
S7_RiskClassPerson(?p) ^ Effected_Allergen(?p,?f) → PersonAtRisk(?p)
1 · OWL+SWRL → Drools
2 · Run Drools
3 · Drools → OWL
Şematik gösterim. Bu üç düğme, Java'da tek infer() çağrısıdır.
Protégé ekranı: motor günlüğü
SWRLTab › Drools Rule Engine › Console
Transferred 118 OWL axioms and 7 SWRL rules to rule engine
Ran rule engine. Inferred 14 axioms (812 ms)
Transferred 14 inferred axioms to OWL model
Üç satır, üç düğmeye karşılık gelir. Üçüncü satır yoksa ontoloji değişmemiştir — sınıfta en sık atlanan adım budur.
Protégé ekranı: SQWRLTab
SWRLTabSQWRLTab
Person(?p) ^ hasName(?p, ?n) ^ hasBMI(?p, ?b) -> sqwrl:select(?n, ?b) ^ sqwrl:orderByDescending(?b)
nb
AYNUR33.43
FATMA28.26
MEHMET26.60
RunSave as CSV
Şematik gösterim. Sorgu ontolojiyi değiştirmediği için istediğiniz kadar deneyebilirsiniz.
Protégé ekranı: kural sonrası TC_001
Individuals by class › Person › TC_001
Types
Person
Adult · PersonAtRisk (S5, S7)
Property assertions
Effected_Allergen Nisin (S6)
hasBMI 23.92 (S4)
Sarı satırlar kural motorunun yazdıklarıdır ve dosyada kalıcıdır — reasoner çıkarımından farkı budur.
05
Avantajlar ve Tam Akış
Sekiz adımda uçtan uca çalışan sistem.
SWRL API'nin avantajları
- Tek satırla çıkarım: infer() üç adımı birleştirir.
- Kalıcı sonuç: çıktı asserted yazılır, sıradan API ile okunur.
- Metinden kural: Protégé sözdizimi doğrudan ayrıştırılır.
- Aritmetik: reasoner'ın yapamadığını yapar.
- Sorgu bütünleşik: SQWRL aynı gövdeyi kullanır, yeni dil öğrenilmez.
- Otomasyon: servis, zamanlanmış iş, test.
- İzlenebilirlik: hangi kural hangi aksiyomu yazdı — raporlanabilir.
- Taşınabilirlik: Protégé'de tasarla, üretimde çalıştır.
Sınırları da bilin
| Sınır | Sonucu | Ne yapmalı |
| Olumsuzlama yok | "Yok" bilgisi yazılamaz | SQWRL küme farkı |
| DL-safe kısıt | Anonim bireyler görülmez | Bireyleri adlandır |
| Literal tipi sessiz hata | Boş sonuç | Aksiyom farkını ölç |
| Bellek içi çalışma | Çok büyük veride yavaş | Parçalı işle |
| Sürüm hassasiyeti | NoSuchMethodError | Tek OWL API dalı |
Main.java — sekiz adımlı akış
| Adım | İş | Araç |
| 1 | Ontolojiyi yükle | OWL API |
| 2 | Envanteri yazdır | OWL API |
| 3 | Kural öncesi denetim | HermiT |
| 4 | Kuralları listele | SWRL API |
| 5 | infer() — kuralları çalıştır | Drools |
| 6 | SQWRL sorguları | SQWRL |
| 7 | Kural sonrası denetim | HermiT |
| 8 | ALLERGY_INFERRED.owl kaydet | OWL API |
Akışın çekirdeği: on satır
OWLOntology ont = man.loadOntologyFromOntologyDocument(owlFile);
OWLReasoner hermit = new ReasonerFactory().createReasoner(ont);
System.out.println("Tutarli mi? " + hermit.isConsistent());
SWRLRuleEngine engine = SWRLAPIFactory.createSWRLRuleEngine(ont);
engine.infer();
SQWRLQueryEngine q = SWRLAPIFactory.createSQWRLQueryEngine(ont);
printResult(q.runSQWRLQuery("Q2", RISK_QUERY));
man.saveOntology(ont, new RDFXMLDocumentFormat(), inferredIRI);
Dönem sonu çıktısı
ADIM 3 — HermiT ON Denetim
Tutarli mi? true
PersonAtRisk uyeleri (BOS beklenir): []
ADIM 5 — SWRLRuleEngine.infer()
14 aksiyom yazildi (812 ms)
ADIM 6 — SQWRL
Q1 Ayse 23.92 FATMA 28.26 MEHMET 26.60 AYNUR 33.43
Q2 Ayse EAN_00004 Nisin | MEHMET EAN_00003 Casein
ADIM 7 — HermiT SON Denetim
PersonAtRisk : [TC_001, TC_002, TC_003, TC_004]
Adult : [TC_001, TC_003, TC_004]
06
Final Projesi
Uçtan uca çalışan sistemin teslimi.
Final projesi — teslim
- Ontoloji: en az 8 sınıf, 12 özellik, 40 birey.
- En az 8 SWRL kuralı; biri aritmetik, biri zincir.
- 3 SQWRL sorgusu; biri toplulaştırma, biri küme işlemi.
- Sekiz adımlı Java uygulaması.
- Kural öncesi/sonrası karşılaştırma raporu.
Dosyalar
ontology.owl
ontology_inferred.owl
maven-project/
rapor.pdf (8-10 sayfa)
sunum.pdf (10 dakika)
Final değerlendirme ölçütleri
| Ölçüt | Ağırlık | Beklenen |
| Ontoloji tasarımı | 20% | Kısıtlar gerekçeli, tutarlı |
| Kural tabanı | 25% | Çeşitli, güvenli, test edilmiş |
| SQWRL raporlama | 15% | Toplulaştırma ve küme işlemi |
| Java uygulaması | 25% | Sekiz adım çalışıyor |
| Rapor ve sunum | 15% | Kararlar savunulmuş |
Kaynaklar
- W3C — SWRL: A Semantic Web Rule Language Combining OWL and RuleML, 2004.
- O'Connor, M., Das, A. — SQWRL: A Query Language for OWL, OWLED 2009.
- SWRLAPI belgeleri ve wiki — github.com/protegeproject/swrlapi.
- O'Connor, M. et al. — Supporting Rule System Interoperability on the Semantic Web with SWRL, ISWC 2005.
- Drools belgeleri — ileri zincirleme ve çakışma çözümü.
Özet • 1 / 2
SWRL API
- SWRL = OWL DL + Horn kuralları; RDFS/OWL'un yapamadığını yapar.
- infer() Protégé'nin üç düğmesine eşdeğerdir.
- Kural çıktısı asserted yazılır; sıradan API ile okunur, dosyada kalır.
- Kuralı metin olarak eklemek en pratik yoldur.
- Aksiyom farkını ölçmek en hızlı hata ayıklama yöntemidir.
Özet • 2 / 2
SQWRL ve dönem kapanışı
- SQWRL kural gövdesini kullanır; başında sorgu operatörü vardır.
- Ontolojiyi değiştirmez — güvenle denenir.
- Küme farkı, SWRL'de olmayan olumsuzlamayı sağlar.
- Sekiz adım: yükle → denetle → çalıştır → sorgula → kaydet.
On hafta sonunda
Bir gıda etiketinden başlayıp, çıkarım yapan ve gerekçesini gösteren çalışan bir semantik sistem kurdunuz.
IRI → XML → RDF → RDFS → OWL → OWL-S → SWRL → API → Reasoner → SQWRL
Tekrar Soruları
Kendinizi sınayın
- infer() hangi üç işi yapar?
- Kural çıktısı ile reasoner çıkarımı arasındaki fark nedir?
- SQWRL neden ontolojiyi değiştirmez?
- Aksiyom farkı 0 ise nereye bakarsınız?
- Küme farkı hangi sorunu çözer?
- Q1 sorgusu neden infer() öncesi boş döner?
- Drools → OWL adımı atlanırsa ne olur?
- HermiT ve Drools'un iş bölümü nedir?
Alıştırma • Sınıf içi
Sorguyu siz yazın
"Her ürünün kaç alerjen katkı içerdiğini, çoktan aza sıralı" bir SQWRL sorgusu yazın.
Product(?u) ^ Contain(?u, ?f)
^ ______(?f, ?al)
-> sqwrl:______(?u)
^ sqwrl:______(?u)
Sorular
- Hangi ürün başa gelir?
- Ascorbic_Acid sayılır mı? Neden?
- Bu sorgu infer() öncesi çalışır mı?